/* Universidad del Valle de Guatemala
 * HojaT4.java
 * Mariana Castillo, 12374
 * Julio Maldonado, 12377
 * Seccion 30, Algoritmos y Estructura de Datos
 * Fecha: 03/07/13
 * Se ejecuta el programa y se elige la implementacion a utilizar*
 */

package hojat4;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Scanner;

public class HojaT4 {
    public static void main(String[] args) {
        // TODO code application logic here
        Scanner scan= new Scanner(System.in);
        String implementacion, tlista;
        int z=0;
        int validar = 0; //Esta variable controla si el archivo tiene un sucecion correcta o hay algo malo en el.
        File archivo = null; // variable archivo contendra la el archivo a analizar
        FileReader fr = null; // variable fr sirve para leer el arhivo mas adelante
        BufferedReader br = null; // br es una variable que servira para complementar la lectura del archivo
        while(z==0){
            System.out.println("Elija el tipo de Implementacion ARRAYLIST, VECTOR O LISTA. (ARRAY,VECTOR, LISTA)");
            implementacion= scan.nextLine();
            // Se revisa que se ingrese una opcion valida
            if((implementacion.equalsIgnoreCase("ARRAY"))||(implementacion.equalsIgnoreCase("VECTOR"))||(implementacion.equalsIgnoreCase("LISTA"))){
                //Se termina el ciclo de eleccion de implementacion
                z=1;
                if(implementacion.equalsIgnoreCase("LISTA")){
                    int z1=0;
                    while(z1==0){
                        System.out.println("Elija el tipo de LISTA SIMPLE, DOUBLE O CIRCULAR. (Sl,DL, LC)");
                        tlista= scan.nextLine();

                        if((tlista.equalsIgnoreCase("SL"))||(tlista.equalsIgnoreCase("DL"))||(tlista.equalsIgnoreCase("LC"))){
                            z1=1;
                            
                            //Se utiliza singleton para verificar que solo se instancia una lista
                            ListFactory<Double> lista= ListFactory.getInstance();
                            //Se utilza factory para elegir el tipo de lista
                            List<Double> lista2= lista.getList(tlista.toUpperCase());


                            
                            //SE LEE EL ARCHIVO DE TEXTO y SE REALIZA EL CALCULO
                            try{  // se realiza un try catch para asegurarse que el archivo este correcto

                              archivo= new File("C:\\Java\\datos.txt"); // se localiza el archivo a analizar
                              fr = new FileReader(archivo); // se lee el archivo 
                              br = new BufferedReader(fr); // el archivo se coloca en el buffer

                              String linea; // variable linea contendra toda la cadena de caracteres que contenga el archivo
                              System.out.println("CALCULO");
                              while((linea=br.readLine())!=null){ // mientras haya caracteres seguira ejecutandose el programa

                                  for(int i=0;i<linea.length(); i++){ // este for sirve paraa recorrer todos los caracteres que se encuentren en el archivo

                                      System.out.print(linea.charAt(i));// Se imprime el string de archivo datos.txt
                                      int comparar = (int)linea.charAt(i); // comparar en una variable que contendra los codigos char de todo lo que se encuentre en el archivo.

                                      if (comparar>=48 &&  comparar<=57 ) { // si la comparaacion que hace con los codigos char estan entre 49 y 57 significa que se ha encontrado un numero.
                                          if(lista2.size()!=2){ // esta condicion revisa si en el stack hay mas de dos elementos, si no hay entonces guarda el numero siguiente y si hay mas de dos significa que el archivo tiene una sucesion incorrecta
                                              double numero = Double.parseDouble(linea.substring(i,i+1)); // la variable numero connvierte el carcter string en un double.
                                              lista2.addLast(numero); // esto almacena el numero en la pila.

                                        }else{

                                          System.out.println("El Archivo tiene una secuencia mala"); // si hay mas de dos numeros queriendo entrar a la pila, este es el mensaje que saldra por progrmacion defensiva
                                          validar = validar+1; // la variable validar se activa porque hay algo malo en el archivo


                                          }


                                        }else{ // si no se dectan numeros entonces eso quiere decir que son espacion o operaciones y en esta parte solo se toman encuenta las operaciones por lo que los espacios desaparecen automaticamente

                                          if ((int)linea.charAt(i)==42){ // aqui se compara si el operando es una mulplicacion y se quitan los dos numeros que esxisten en la pila, hace la operacion y el resultado se introduce otra vez en la pila.

                                          double num1=lista2.removeLast();
                                          double num2=lista2.removeLast();

                                          double multiplicacion = num1*num2;

                                          lista2.addLast(multiplicacion);



                                          }

                                          if ((int)linea.charAt(i)==43){  // aqui se compara si el operando es una suma y se quitan los dos numeros que esxisten en la pila, hace la operacion y el resultado se introduce otra vez en la pila.

                                          double num3=lista2.removeLast();
                                          double num4=lista2.removeLast();

                                          double suma = num3+num4;

                                          lista2.addLast(suma);
                                          }

                                           if ((int)linea.charAt(i)==45){  // aqui se compara si el operando es una resta y se quitan los dos numeros que esxisten en la pila, hace la operacion y el resultado se introduce otra vez en la pila.

                                          double num5=lista2.removeLast();
                                          double num6=lista2.removeLast();

                                          double resta = num6-num5;

                                          lista2.addLast(resta);

                                          }

                                           if ((int)linea.charAt(i)==47){  // aqui se compara si el operando es una division y se quitan los dos numeros que esxisten en la pila, hace la operacion y el resultado se introduce otra vez en la pila.



                                               double num7=lista2.removeLast();
                                               double num8=lista2.removeLast();
                                               if  (num7!=0){
                                               try{
                                               double division = num8/num7;

                                               lista2.addLast(division);}
                                               catch(Exception a){}
                                               }else{
                                                   System.out.println("\nError al dividir por 0");
                                                   validar=validar + 1;
                                                   i=linea.length();
                                               }
                                           }
                                       }    
                                   }
                              }
                          }
                          catch(Exception e){
                              e.printStackTrace();

                          }finally{ // esto se realiza para terminar bien la ejecucion del archivo
                              try{

                                  if(null!= fr)
                                      fr.close();

                              }catch(Exception e2){

                              e2.printStackTrace();
                              }

                          }
                           double result=lista2.get(); // en la variable result se guardara el resultado final de la operacion
                           if(validar!=1){ // se verifica que el arhivo este bien
                               System.out.println("\nEl resultado final es: "+result); // aqui se imprime para poder observar el resultado
                           }

                        //***********
                        }
                        else{
                            System.out.println("ERROR: Ingrese una opcion valida (SL, DL,LC)\n");
                        }
                    }
                // IMPLEMENTACION ARRAYLIST Y VECTOR
                }else{
                    
                    //Se verifica que el objeto sea instanciado una sola vez
                    StackFactory_Singleton<Double> c1 =  StackFactory_Singleton.getInstance();

                    //Se elige la implementacion ArrayList, Vector o Lista dependiendo del string ingresado
                    Stack<Double> c= c1.getImplementacion(implementacion.toUpperCase());

                    // SE LEE EL ARCHIVO TXT
                    try{  // se realiza un try catch para asegurarse que el archivo este correcto

                      archivo= new File("C:\\Java\\datos.txt"); // se localiza el archivo a analizar
                      fr = new FileReader(archivo); // se lee el archivo 
                      br = new BufferedReader(fr); // el archivo se coloca en el buffer

                      String linea; // variable linea contendra toda la cadena de caracteres que contenga el archivo
                      System.out.println("Calculo");
                      while((linea=br.readLine())!=null){ // mientras haya caracteres seguira ejecutandose el programa

                          for(int i=0;i<linea.length(); i++){ // este for sirve paraa recorrer todos los caracteres que se encuentren en el archivo

                              System.out.print(linea.charAt(i));// Se imprime el string de archivo datos.txt
                              int comparar = (int)linea.charAt(i); // comparar en una variable que contendra los codigos char de todo lo que se encuentre en el archivo.

                              if (comparar>=48 &&  comparar<=57 ) { // si la comparaacion que hace con los codigos char estan entre 49 y 57 significa que se ha encontrado un numero.
                                  if(c.size()!=2){ // esta condicion revisa si en el stack hay mas de dos elementos, si no hay entonces guarda el numero siguiente y si hay mas de dos significa que el archivo tiene una sucesion incorrecta
                                      double numero = Double.parseDouble(linea.substring(i,i+1)); // la variable numero connvierte el carcter string en un double.
                                      c.push(numero); // esto almacena el numero en la pila.

                                }else{

                                  System.out.println("El Archivo tiene una secuencia mala"); // si hay mas de dos numeros queriendo entrar a la pila, este es el mensaje que saldra por progrmacion defensiva
                                  validar = validar+1; // la variable validar se activa porque hay algo malo en el archivo


                                  }


                                }else{ // si no se dectan numeros entonces eso quiere decir que son espacion o operaciones y en esta parte solo se toman encuenta las operaciones por lo que los espacios desaparecen automaticamente

                                  if ((int)linea.charAt(i)==42){ // aqui se compara si el operando es una mulplicacion y se quitan los dos numeros que esxisten en la pila, hace la operacion y el resultado se introduce otra vez en la pila.

                                  double num1=c.pop();
                                  double num2=c.pop();

                                  double multiplicacion = num1*num2;

                                  c.push(multiplicacion);



                                  }

                                   if ((int)linea.charAt(i)==43){  // aqui se compara si el operando es una suma y se quitan los dos numeros que esxisten en la pila, hace la operacion y el resultado se introduce otra vez en la pila.

                                  double num3=c.pop();
                                  double num4=c.pop();

                                  double suma = num3+num4;

                                  c.push(suma);
                                  }

                                   if ((int)linea.charAt(i)==45){  // aqui se compara si el operando es una resta y se quitan los dos numeros que esxisten en la pila, hace la operacion y el resultado se introduce otra vez en la pila.

                                  double num5=c.pop();
                                  double num6=c.pop();

                                  double resta = num6-num5;

                                  c.push(resta);

                                  }

                                   if ((int)linea.charAt(i)==47){  // aqui se compara si el operando es una division y se quitan los dos numeros que esxisten en la pila, hace la operacion y el resultado se introduce otra vez en la pila.



                                       double num7=c.pop();
                                       double num8=c.pop();
                                       if  (num7!=0){
                                       try{
                                       double division = num8/num7;

                                       c.push(division);}
                                       catch(Exception a){}
                                       }else{
                                           System.out.println("\nError al dividir por 0");
                                           validar=validar + 1;
                                           i=linea.length();
                                       }
                                   }
                               }    
                           }
                      }
                  }
                  catch(Exception e){
                      e.printStackTrace();

                  }finally{ // esto se realiza para terminar bien la ejecucion del archivo
                      try{

                          if(null!= fr)
                              fr.close();

                      }catch(Exception e2){

                      e2.printStackTrace();
                      }

                  }
                   double result=c.peek(); // en la variable result se guardara el resultado final de la operacion
                   if(validar!=1){ // se verifica que el arhivo este bien
                       System.out.println("\nEl resultado final es: "+result); // aqui se imprime para poder observar el resultado
                   }

                else{
                    System.out.println("ERROR: Ingrese una opcion valida. (ARRAY, VECTOR, LISTA)\n");
                }
            }
          }
        }
    }
}
